home *** CD-ROM | disk | FTP | other *** search
/ Freelog 125 / Freelog_MarsAvril2015_No125.iso / Internet / gpodder / gpodder-3.8.3-setup.exe / {app} / src / mygpoclient / locator.py < prev    next >
Text File  |  2013-02-08  |  13KB  |  319 lines

  1. # -*- coding: utf-8 -*-
  2. # gpodder.net API Client
  3. # Copyright (C) 2009-2013 Thomas Perl and the gPodder Team
  4. #
  5. # This program is free software: you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation, either version 3 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program.  If not, see <http://www.gnu.org/licenses/>.
  17.  
  18. import mygpoclient
  19.  
  20. import os
  21. import urllib
  22.  
  23. from mygpoclient import util
  24.  
  25. class Locator(object):
  26.     """URI Locator for API endpoints
  27.  
  28.     This helper class abstracts the URIs for the gpodder.net
  29.     webservice and provides a nice facility for generating API
  30.     URIs and checking parameters.
  31.     """
  32.     SIMPLE_FORMATS = ('opml', 'json', 'txt')
  33.  
  34.     SETTINGS_TYPES = ('account', 'device', 'podcast', 'episode')
  35.  
  36.     def __init__(self, username, host=mygpoclient.HOST,
  37.             version=mygpoclient.VERSION):
  38.         self._username = username
  39.         self._simple_base = 'http://%(host)s' % locals()
  40.         self._base = 'http://%(host)s/api/%(version)s' % locals()
  41.  
  42.     def _convert_since(self, since):
  43.         """Convert "since" into a numeric value
  44.  
  45.         This is internally used for value-checking.
  46.         """
  47.         try:
  48.             return int(since)
  49.         except ValueError:
  50.             raise ValueError('since must be a numeric value (or None)')
  51.  
  52.     def subscriptions_uri(self, device_id, format='opml'):
  53.         """Get the Simple API URI for a subscription list
  54.  
  55.         >>> locator = Locator('john')
  56.         >>> locator.subscriptions_uri('n800')
  57.         'http://gpodder.net/subscriptions/john/n800.opml'
  58.         >>> locator.subscriptions_uri('ipod', 'txt')
  59.         'http://gpodder.net/subscriptions/john/ipod.txt'
  60.         """
  61.         if format not in self.SIMPLE_FORMATS:
  62.             raise ValueError('Unsupported file format')
  63.  
  64.         filename = '%(device_id)s.%(format)s' % locals()
  65.         return util.join(self._simple_base,
  66.                 'subscriptions', self._username, filename)
  67.  
  68.     def toplist_uri(self, count=50, format='opml'):
  69.         """Get the Simple API URI for the toplist
  70.  
  71.         >>> locator = Locator(None)
  72.         >>> locator.toplist_uri()
  73.         'http://gpodder.net/toplist/50.opml'
  74.         >>> locator.toplist_uri(70)
  75.         'http://gpodder.net/toplist/70.opml'
  76.         >>> locator.toplist_uri(10, 'json')
  77.         'http://gpodder.net/toplist/10.json'
  78.         """
  79.         if format not in self.SIMPLE_FORMATS:
  80.             raise ValueError('Unsupported file format')
  81.  
  82.         filename = 'toplist/%(count)d.%(format)s' % locals()
  83.         return util.join(self._simple_base, filename)
  84.  
  85.     def suggestions_uri(self, count=10, format='opml'):
  86.         """Get the Simple API URI for user suggestions
  87.  
  88.         >>> locator = Locator('john')
  89.         >>> locator.suggestions_uri()
  90.         'http://gpodder.net/suggestions/10.opml'
  91.         >>> locator.suggestions_uri(50)
  92.         'http://gpodder.net/suggestions/50.opml'
  93.         >>> locator.suggestions_uri(70, 'json')
  94.         'http://gpodder.net/suggestions/70.json'
  95.         """
  96.         if format not in self.SIMPLE_FORMATS:
  97.             raise ValueError('Unsupported file format')
  98.  
  99.         filename = 'suggestions/%(count)d.%(format)s' % locals()
  100.         return util.join(self._simple_base, filename)
  101.  
  102.     def search_uri(self, query, format='opml'):
  103.         """Get the Simple API URI for podcast search
  104.  
  105.         >>> locator = Locator(None)
  106.         >>> locator.search_uri('outlaws')
  107.         'http://gpodder.net/search.opml?q=outlaws'
  108.         >>> locator.search_uri(':something?', 'txt')
  109.         'http://gpodder.net/search.txt?q=%3Asomething%3F'
  110.         >>> locator.search_uri('software engineering', 'json')
  111.         'http://gpodder.net/search.json?q=software+engineering'
  112.         """
  113.         if format not in self.SIMPLE_FORMATS:
  114.             raise ValueError('Unsupported file format')
  115.  
  116.         query = urllib.quote_plus(query)
  117.         filename = 'search.%(format)s?q=%(query)s' % locals()
  118.         return util.join(self._simple_base, filename)
  119.  
  120.     def add_remove_subscriptions_uri(self, device_id):
  121.         """Get the Advanced API URI for uploading list diffs
  122.  
  123.         >>> locator = Locator('bill')
  124.         >>> locator.add_remove_subscriptions_uri('n810')
  125.         'http://gpodder.net/api/2/subscriptions/bill/n810.json'
  126.         """
  127.         filename = '%(device_id)s.json' % locals()
  128.         return util.join(self._base,
  129.                 'subscriptions', self._username, filename)
  130.  
  131.     def subscription_updates_uri(self, device_id, since=None):
  132.         """Get the Advanced API URI for downloading list diffs
  133.  
  134.         The parameter "since" is optional and should be a numeric
  135.         value (otherwise a ValueError is raised).
  136.  
  137.         >>> locator = Locator('jen')
  138.         >>> locator.subscription_updates_uri('n900')
  139.         'http://gpodder.net/api/2/subscriptions/jen/n900.json'
  140.         >>> locator.subscription_updates_uri('n900', 1234)
  141.         'http://gpodder.net/api/2/subscriptions/jen/n900.json?since=1234'
  142.         """
  143.         filename = '%(device_id)s.json' % locals()
  144.         if since is not None:
  145.             since = self._convert_since(since)
  146.             filename += '?since=%(since)d' % locals()
  147.  
  148.         return util.join(self._base,
  149.                 'subscriptions', self._username, filename)
  150.  
  151.     def upload_episode_actions_uri(self):
  152.         """Get the Advanced API URI for uploading episode actions
  153.  
  154.         >>> locator = Locator('thp')
  155.         >>> locator.upload_episode_actions_uri()
  156.         'http://gpodder.net/api/2/episodes/thp.json'
  157.         """
  158.         filename = self._username + '.json'
  159.         return util.join(self._base, 'episodes', filename)
  160.  
  161.     def download_episode_actions_uri(self, since=None,
  162.             podcast=None, device_id=None):
  163.         """Get the Advanced API URI for downloading episode actions
  164.  
  165.         The parameter "since" is optional and should be a numeric
  166.         value (otherwise a ValueError is raised).
  167.  
  168.         Both "podcast" and "device_id" are optional and exclusive:
  169.  
  170.         "podcast" should be a podcast URL
  171.         "device_id" should be a device ID
  172.  
  173.         >>> locator = Locator('steve')
  174.         >>> locator.download_episode_actions_uri()
  175.         'http://gpodder.net/api/2/episodes/steve.json'
  176.         >>> locator.download_episode_actions_uri(since=1337)
  177.         'http://gpodder.net/api/2/episodes/steve.json?since=1337'
  178.         >>> locator.download_episode_actions_uri(podcast='http://example.org/episodes.rss')
  179.         'http://gpodder.net/api/2/episodes/steve.json?podcast=http%3A//example.org/episodes.rss'
  180.         >>> locator.download_episode_actions_uri(since=2000, podcast='http://example.com/')
  181.         'http://gpodder.net/api/2/episodes/steve.json?since=2000&podcast=http%3A//example.com/'
  182.         >>> locator.download_episode_actions_uri(device_id='ipod')
  183.         'http://gpodder.net/api/2/episodes/steve.json?device=ipod'
  184.         >>> locator.download_episode_actions_uri(since=54321, device_id='ipod')
  185.         'http://gpodder.net/api/2/episodes/steve.json?since=54321&device=ipod'
  186.         """
  187.         if podcast is not None and device_id is not None:
  188.             raise ValueError('must not specify both "podcast" and "device_id"')
  189.  
  190.         filename = self._username + '.json'
  191.  
  192.         params = []
  193.         if since is not None:
  194.             since = str(self._convert_since(since))
  195.             params.append(('since', since))
  196.  
  197.         if podcast is not None:
  198.             params.append(('podcast', podcast))
  199.  
  200.         if device_id is not None:
  201.             params.append(('device', device_id))
  202.  
  203.         if params:
  204.             filename += '?' + '&'.join('%s=%s' % (key, urllib.quote(value)) for key, value in params)
  205.  
  206.         return util.join(self._base, 'episodes', filename)
  207.  
  208.     def device_settings_uri(self, device_id):
  209.         """Get the Advanced API URI for setting per-device settings uploads
  210.  
  211.         >>> locator = Locator('mike')
  212.         >>> locator.device_settings_uri('ipod')
  213.         'http://gpodder.net/api/2/devices/mike/ipod.json'
  214.         """
  215.         filename = '%(device_id)s.json' % locals()
  216.         return util.join(self._base, 'devices', self._username, filename)
  217.  
  218.     def device_list_uri(self):
  219.         """Get the Advanced API URI for retrieving the device list
  220.  
  221.         >>> locator = Locator('jeff')
  222.         >>> locator.device_list_uri()
  223.         'http://gpodder.net/api/2/devices/jeff.json'
  224.         """
  225.         filename = self._username + '.json'
  226.         return util.join(self._base, 'devices', filename)
  227.  
  228.     def toptags_uri(self, count=50):
  229.         """Get the Advanced API URI for retrieving the top Tags
  230.  
  231.         >>> locator = Locator(None)
  232.         >>> locator.toptags_uri()
  233.         'http://gpodder.net/api/2/tags/50.json'
  234.         >>> locator.toptags_uri(70)
  235.         'http://gpodder.net/api/2/tags/70.json'
  236.         """
  237.         filename = '%(count)d.json' % locals()
  238.         return util.join(self._base, 'tags', filename)
  239.  
  240.     def podcasts_of_a_tag_uri(self, tag, count=50):
  241.         """Get the Advanced API URI for retrieving the top Podcasts of a Tag
  242.  
  243.         >>> locator = Locator(None)
  244.         >>> locator.podcasts_of_a_tag_uri('linux')
  245.         'http://gpodder.net/api/2/tag/linux/50.json'
  246.         >>> locator.podcasts_of_a_tag_uri('linux',70)
  247.         'http://gpodder.net/api/2/tag/linux/70.json'
  248.         """
  249.         filename = '%(tag)s/%(count)d.json' % locals()
  250.         return util.join(self._base, 'tag', filename)
  251.  
  252.     def podcast_data_uri(self, podcast_url):
  253.         """Get the Advanced API URI for retrieving Podcast Data
  254.  
  255.         >>> locator = Locator(None)
  256.         >>> locator.podcast_data_uri('http://podcast.com')
  257.         'http://gpodder.net/api/2/data/podcast.json?url=http%3A//podcast.com'
  258.         """
  259.         filename = 'podcast.json?url=%s' % urllib.quote(podcast_url) 
  260.         return util.join(self._base, 'data', filename)
  261.     
  262.     def episode_data_uri(self, podcast_url, episode_url):
  263.         """Get the Advanced API URI for retrieving Episode Data
  264.  
  265.         >>> locator = Locator(None)
  266.         >>> locator.episode_data_uri('http://podcast.com','http://podcast.com/foo')
  267.         'http://gpodder.net/api/2/data/episode.json?podcast=http%3A//podcast.com&url=http%3A//podcast.com/foo'
  268.         """
  269.         filename = 'episode.json?podcast=%s&url=%s' % (urllib.quote(podcast_url), urllib.quote(episode_url))
  270.         return util.join(self._base, 'data', filename)
  271.  
  272.     def favorite_episodes_uri(self):
  273.         """Get the Advanced API URI for listing favorite episodes
  274.  
  275.         >>> locator = Locator('mike')
  276.         >>> locator.favorite_episodes_uri()
  277.         'http://gpodder.net/api/2/favorites/mike.json'
  278.         """
  279.         filename = self._username + '.json'
  280.         return util.join(self._base, 'favorites', filename)
  281.  
  282.     def settings_uri(self, type, scope_param1, scope_param2):
  283.         """Get the Advanced API URI for retrieving or saving Settings
  284.         
  285.         Depending on the Type of setting scope_param2 or scope_param1 and scope_param2 are
  286.         not necessary.
  287.  
  288.         >>> locator = Locator('joe')
  289.         >>> locator.settings_uri('account',None,None)
  290.         'http://gpodder.net/api/2/settings/joe/account.json'
  291.         >>> locator.settings_uri('device','foodevice',None)
  292.         'http://gpodder.net/api/2/settings/joe/device.json?device=foodevice'
  293.         >>> locator.settings_uri('podcast','http://podcast.com',None)
  294.         'http://gpodder.net/api/2/settings/joe/podcast.json?podcast=http%3A//podcast.com'
  295.         >>> locator.settings_uri('episode','http://podcast.com','http://podcast.com/foo')
  296.         'http://gpodder.net/api/2/settings/joe/episode.json?podcast=http%3A//podcast.com&episode=http%3A//podcast.com/foo'
  297.         """
  298.         if type not in self.SETTINGS_TYPES:
  299.             raise ValueError('Unsupported Setting Type')
  300.  
  301.         filename = self._username + '/%(type)s.json' % locals()
  302.  
  303.         if type is 'device':
  304.             if scope_param1 is None:
  305.                 raise ValueError('Devicename not specified')
  306.             filename += '?device=%(scope_param1)s' % locals()
  307.  
  308.         if type is 'podcast':
  309.             if scope_param1 is None:
  310.                 raise ValueError('Podcast URL not specified')
  311.             filename += '?podcast=%s' % urllib.quote(scope_param1)
  312.  
  313.         if type is 'episode':
  314.             if (scope_param1 is None) or (scope_param2 is None):
  315.                 raise ValueError('Podcast or Episode URL not specified')
  316.             filename += '?podcast=%s&episode=%s' % (urllib.quote(scope_param1), urllib.quote(scope_param2))
  317.  
  318.         return util.join(self._base, 'settings' , filename)
  319.